package com.paul.log.aop;

import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.paul.common.annotation.OperLog;
import com.paul.common.constant.RedisKeyConst;
import com.paul.common.enums.AuthEnum;
import com.paul.common.utils.HttpContextUtil;
import com.paul.common.utils.IpUtil;
import com.paul.redis.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author ：zmk
 * @date ：Created in 2021/11/11 10:34
 * @description：操作记录日志切面配置
 */
@Order(3)
@Aspect
@Component("OperLogAop")
public class OperLogAop {
    private final static Logger logger = LoggerFactory.getLogger(OperLogAop.class);
    @Autowired
    private RedisUtil redisUtil;

    //指定切点,使用after 让该切面在方法执行完成后切入
    @After("(execution(public * com.paul.*.api.controller..*(..))) && @annotation(operLog)")
    public void after(JoinPoint point, OperLog operLog) throws Throwable {

        try {
            // 拦截的action方法上面的标记是否包含 MethodLog 的注解
//            Map<String, Object> map = getMthodRemark(point);
//            if (map.isEmpty()) {
//                // 没有MethodLog 注解标记 ,无此配置,直接返回
//                return;
//            }

            if (null == operLog) {
                return;
            }
            HttpServletRequest request = HttpContextUtil.getRequest();
            if (null == request) {
                return;
            }
            String header = this.getHeader(HttpContextUtil.getRequest());

            //判断hender:Authorization是否有值
            if (header == null || StringUtils.isBlank(header)) {
                return;
            }
            //解析token
//            String token = header.split(" ")[1];
//            UserAuthPrincipal userAuthPrincipal = JWTUtil.getAuthUser(token);
//            if (null == userAuthPrincipal) {
//                return;
//            }
            //获取信息
            String userAgent = request.getHeader("User-Agent");
            String ip = IpUtil.getIpAddr(request);
            UserAgent ua = UserAgentUtil.parse(userAgent);
            //构建操作日志对象
            Map<String, Object> map = new HashMap<>();
            map.put("ip", ip);
            map.put("content", operLog.operModul() + ":" + operLog.operDesc());
            map.put("addr", IpUtil.getCityInfoByIp(ip));
            map.put("Browser", ua.getBrowser().toString());
//            map.put("operid", userAuthPrincipal.getUserId());
            map.put("path", request.getServletPath());

            logger.info(JSON.toJSONString(map));
        } catch (Exception e) {
            logger.error("记录操作日志出错：{}", e);
        }
    }

    // 获取方法的中文备注____用于记录用户的操作日志描述
    @SuppressWarnings("rawtypes")
    public static Map<String, Object> getMthodRemark(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Map<String, Object> map = Maps.newHashMap();
        Class targetClass = Class.forName(targetName);
        Method[] method = targetClass.getMethods();
        for (Method m : method) {
            if (m.getName().equals(methodName)) {
                Class[] tmpCs = m.getParameterTypes();
                if (tmpCs.length == arguments.length) {
                    OperLog operLog = m.getAnnotation(OperLog.class);
                    if (operLog != null) {
                        map.put("operModul", operLog.operModul());
                        map.put("operDesc", operLog.operDesc());
                        map.put("operLevel", operLog.operLevel());
                        map.put("operType", operLog.operType());
                    }
                    break;
                }
            }
        }
        return map;
    }

    public String getHeader(HttpServletRequest request) {
        String header = request.getHeader("Authorization");
        if (StringUtils.isBlank(header)) {
            header = request.getParameter("Authorization");
        }
        //解决清除上一次请求记录信息
//        SecurityContextHolder.clearContext();
//        if (header == null || !header.toLowerCase().startsWith("bearer ")) {
//            SecurityContextHolder.clearContext();
//            chain.doFilter(request, response);
//            return;
//        }
        if (header == null || header.split(" ").length != 2) {
            return "";
        }

        if ((header.startsWith(AuthEnum.Bearer.toString()) && header.length() == 6) || (header.startsWith(AuthEnum.Token.toString()) && header.length() == 5)) {
            return "";
        }

        //token认证，但是最终是Bearer认证
        if (header.startsWith(AuthEnum.Token.toString()) && header.split(" ").length == 2) {
            String cacheTokenKey = String.format(RedisKeyConst.TOKEN_AUTH, header.split(" ")[1]);
            Object obj = redisUtil.get(cacheTokenKey);
            header = obj.toString();
        }
        return header;
    }

}
